home *** CD-ROM | disk | FTP | other *** search
- ## -*-Tcl-*-
- # ###################################################################
- # AlphaTcl - core Tcl engine
- #
- # FILE: "hook.tcl"
- # created: 18/7/97 {5:10:18 pm}
- # last update: 01/16/2001 {18:45:28 PM}
- # Author: Vince Darley
- # E-mail: <vince@santafe.edu>
- # mail: 317 Paseo de Peralta
- # Santa Fe, NM 87501, USA
- # www: <http://www.santafe.edu/~vince/>
- #
- # Copyright (c) 1997-2000 Vince Darley, all rights reserved
- #
- # Description:
- #
- # Allows procedures to be registered and called at a specific time,
- # according to the current mode. This means it is no longer necessary
- # or desireable to rename the standard hook procedures. Previously
- # you had to do this:
- #
- # if {[info commands blahSaveHook] == ""} {
- # rename saveHook blahSaveHook
- # proc saveHook {name} { ... ; blahSaveHook $name}
- # }
- #
- # But now you just need to add a line like this to your code:
- #
- # hook::register 'hook-name' 'your proc' 'mode' ?... 'mode'?
- #
- # Here are two examples:
- #
- # hook::register savePostHook codeWarrior_modified "C++" "C"
- # hook::register savePostHook ftpPostHook
- #
- # If you don't include a 'mode', then your proc will be called no
- # matter what the current mode is. Avoid this unless absolutely
- # necessary.
- #
- # Use of such lists as 'savePostHooks' is obsolete.
- # These lists are ignored, use hook::register instead.
- #
- # History
- #
- # modified by rev reason
- # -------- --- --- -----------
- # 18/7/97 VMD 1.0 original
- # 22/7/97 VMD 1.1 fixed all bugs ;-) and added the above examples.
- # ###################################################################
- ##
-
- namespace eval hook {}
- set hook::version 1.1
-
- proc hook::register {hook procname args} {
- if {![llength $args]} {lappend args "*"}
- namesp ::hook::${hook}
- global hook::${hook}
- foreach mode $args {
- if {![info exists hook::${hook}($mode)] || \
- [lsearch -exact [set hook::${hook}($mode)] $procname] == -1} {
- lappend hook::${hook}($mode) $procname
- }
- }
- }
-
- proc hook::anythingRegistered {hook {_detail ""}} {
- global hook::${hook}
- if {[string length $_detail]} {
- return [info exists hook::${hook}($_detail)]
- } else {
- return [array exists hook::$hook]
- }
- }
-
- proc hook::information {{hook ""} {_mode ""}} {
- if {$hook == ""} {
- # just list the names of hooks which exist
- set l [uplevel #0 {info vars hook::*}]
- foreach a $l {
- if {![uplevel #0 "array exists $a"]} {
- set i [lsearch $l $a]
- set l [lreplace $l $i $i]
- }
- }
- regsub -all "hook::" $l "" l
- return $l
- } else {
- global hook::${hook}
- if {${_mode} == ""} {
- # return all the attached procs for given hook
- if {[array exists hook::$hook]} {
- return [array get hook::${hook}]
- } else {
- return ""
- }
- } else {
- if {[info exists hook::${hook}($_mode)]} {
- return [set hook::${hook}($_mode)]
- } else {
- return ""
- }
- }
- }
- }
-
- proc hook::deregister {hook {procname ""} args} {
- if {![llength $args]} {set args "*"}
- namesp hook::${hook}
- global hook::${hook}
- if {$procname == ""} {
- # clear all hooks
- unset hook::${hook}
- } else {
- foreach mode $args {
- if {[info exists hook::${hook}($mode)] && \
- [set i [lsearch -exact [set hook::${hook}($mode)] $procname]] != -1} {
- set new [lreplace [set hook::${hook}($mode)] $i $i]
- if {[llength $new]} {
- set hook::${hook}($mode) $new
- } else {
- unset hook::${hook}($mode)
- }
- }
- }
- }
- }
-
- proc hook::callAll {hook {_mode ""} args} {
- if {[catch "global hook::${hook}"]} {return 0}
- if {$_mode == ""} { global mode ; set _mode $mode }
- set err 0
- if {[info exists hook::${hook}(*)]} {
- foreach proc [set hook::${hook}(*)] {
- incr err [catch {uplevel \#0 [list eval $proc $args]}]
- }
- }
- if {$_mode != "*" && [info exists hook::${hook}($_mode)]} {
- foreach proc [set hook::${hook}($_mode)] {
- incr err [catch {uplevel \#0 [list eval $proc $args]}]
- }
- }
- return $err
- }
-
- ##
- # -------------------------------------------------------------------------
- #
- # "hook::callUntil" --
- #
- # Rather like 'callAll', except it is used to implement a stacked
- # hook. This is a hook in which registered procedures are called
- # one by one, _until_ one of them claims to be able to handle
- # the request. It does that by taking action and returning '1'.
- # Procedures which cannot handle the action return 0.
- #
- # Procedures should not throw an error (although currently we
- # are kind enough to ignore it).
- # -------------------------------------------------------------------------
- ##
- proc hook::callUntil {hook {_mode ""} args} {
- if {[catch "global hook::${hook}"]} {return 0}
- if {$_mode == ""} { global mode ; set _mode $mode }
- if {[info exists hook::${hook}(*)]} {
- foreach proc [set hook::${hook}(*)] {
- if {![catch {uplevel \#0 [list eval $proc $args]} res] && $res} {
- return 1
- }
- }
- }
- if {$_mode != "*" && [info exists hook::${hook}($_mode)]} {
- foreach proc [set hook::${hook}($_mode)] {
- if {![catch {uplevel \#0 [list eval $proc $args]} res] && $res} {
- return 1
- }
- }
- }
- return 0
- }
-
- proc hook::callUntilOk {hook {_mode ""} args} {
- if {[catch "global hook::${hook}"]} {error "No hooks were ok"}
- if {$_mode == ""} { global mode ; set _mode $mode }
- if {[info exists hook::${hook}(*)]} {
- foreach proc [set hook::${hook}(*)] {
- if {![catch {uplevel \#0 [list eval $proc $args]} res]} {
- return $res
- }
- }
- }
- if {$_mode != "*" && [info exists hook::${hook}($_mode)]} {
- foreach proc [set hook::${hook}($_mode)] {
- if {![catch {uplevel \#0 [list eval $proc $args]} res]} {
- return $res
- }
- }
- }
- error "No hooks were ok"
- }
-
-
-
-
-